package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"time"
	"ztchat/global"
)

type Response[T any] struct {
	Data   T      `json:"data"`
	Errmsg string `json:"errmsg"`
	Errno  int    `json:"errno"`
}

type BasicReq struct {
	Type int    `json:"type"`
	Path string `json:"path,omitempty"`
}

type LoginRes struct {
	Status int `json:"status"`
}

type GetListReq struct {
	Type     int `json:"type"`
	PullType int `json:"pull_type"`
}

type ListDetail struct {
	AvatarURL string `json:"avatar_url"`
	NickName  string `json:"nick_name"`
	Remark    string `json:"remark"`
	WxAccount string `json:"wx_account"`
	WxID      string `json:"wx_id"`
}

type GetGroupRes struct {
	List []ListDetail `json:"list"`
}

type SendTextReq struct {
	Type int    `json:"type"`
	WxID string `json:"wx_id"`
	Msg  string `json:"msg"`
}

type SendTextRes struct {
	Status int `json:"status"`
}

func post(client *http.Client, payload interface{}) (*http.Response, error) {
	data, err := json.Marshal(payload)
	if err != nil {
		return nil, fmt.Errorf("error marshaling JSON: %w", err)
	}

	resp, err := client.Post(
		fmt.Sprintf("http://localhost:%d/api", SEND_PORT),
		"application/json",
		bytes.NewBuffer(data),
	)

	if err != nil {
		return nil, fmt.Errorf("error making POST request: %w", err)
	}

	return resp, nil
}

func isLogin(client *http.Client, ticker *time.Ticker) bool {
	payload := BasicReq{Type: 1}

	resp, err := post(client, payload)
	if err != nil {
		log.Println("Error sending request:", err)
		return false
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusOK {
		var response Response[LoginRes]

		body, err := io.ReadAll(resp.Body)

		if err != nil {
			log.Println("Error reading body:", err)
			return false
		}

		if err := json.Unmarshal(body, &response); err != nil {
			log.Println("Error decoding response:", err)
			return false
		}

		log.Println("data:", response.Data)

		if response.Data.Status == 1 {
			log.Println("Logged in.")
			ticker.Stop()
			return true
		}
	}

	log.Println("Login failed, will try again.")
	return false
}

func isLoginOnce(client *http.Client) bool {
	payload := BasicReq{Type: 1}

	resp, err := post(client, payload)
	if err != nil {
		log.Println("Error sending request:", err)
		return false
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusOK {
		var response Response[LoginRes]

		body, err := io.ReadAll(resp.Body)

		if err != nil {
			log.Println("Error reading body:", err)
			return false
		}

		if err := json.Unmarshal(body, &response); err != nil {
			log.Println("Error decoding response:", err)
			return false
		}

		log.Printf("login response: %v\n", response)

		if response.Data.Status == 1 {
			log.Println("User is logged in.")
			return true
		}
	}

	log.Println("Not login yet.")
	return false
}

func getInfo(client *http.Client) global.User {
	payload := BasicReq{Type: 3}
	resp, err := post(client, payload)

	if err != nil {
		log.Println("Error sending request:", err)
		return global.User{}
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusOK {
		var response Response[global.User]

		body, err := io.ReadAll(resp.Body)

		if err != nil {
			log.Println("Error reading body:", err)
			return global.User{}
		}

		if err := json.Unmarshal(body, &response); err != nil {
			log.Println("Error decoding response:", err)
			return global.User{}
		}

		log.Printf("info response: %+v", response)

		return response.Data
	}
	return global.User{}
}

func getUserList(client *http.Client) []ListDetail {
	payload := GetListReq{Type: 5, PullType: 1}

	resp, err := post(client, payload)
	if err != nil {
		log.Println("Error sending request:", err)
		return []ListDetail{}
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusOK {
		var response Response[GetGroupRes]

		body, err := io.ReadAll(resp.Body)

		if err != nil {
			log.Println("Error reading body:", err)
			return []ListDetail{}
		}

		if err := json.Unmarshal(body, &response); err != nil {
			log.Println("Error decoding response:", err)
			return []ListDetail{}
		}

		log.Printf("user response: %+v", response)

		return response.Data.List
	}

	log.Println("Get user list failed.")
	return []ListDetail{}
}

func getGroupList(client *http.Client) []ListDetail {
	payload := GetListReq{Type: 5, PullType: 2}

	resp, err := post(client, payload)
	if err != nil {
		log.Println("Error sending request:", err)
		return []ListDetail{}
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusOK {
		var response Response[GetGroupRes]

		body, err := io.ReadAll(resp.Body)

		if err != nil {
			log.Println("Error reading body:", err)
			return []ListDetail{}
		}

		if err := json.Unmarshal(body, &response); err != nil {
			log.Println("Error decoding response:", err)
			return []ListDetail{}
		}

		log.Printf("group response: %+v", response)

		return response.Data.List
	}

	log.Println("Get group list failed.")
	return []ListDetail{}
}

func sendText(client *http.Client, id string, msg string) bool {
	payload := SendTextReq{Type: 7, WxID: id, Msg: msg}

	resp, err := post(client, payload)
	if err != nil {
		log.Println("Error sending request:", err)
		return false
	}
	defer resp.Body.Close()

	if resp.StatusCode == http.StatusOK {
		var response Response[SendTextRes]

		body, err := io.ReadAll(resp.Body)

		if err != nil {
			log.Println("Error reading body:", err)
			return true
		}

		if err := json.Unmarshal(body, &response); err != nil {
			log.Println("Error decoding response:", err)
			return false
		}

		log.Printf("send text response: %+v\n", response)

		return response.Data.Status == 0
	}

	log.Println("Get group list failed.")
	return false
}

func sendTextEveryOne(client *http.Client, list []ListDetail) {
	for _, elem := range list {
		if sendText(client, elem.WxID, "你好啊，"+elem.NickName) {
			log.Printf("向【" + elem.NickName + "】发送信息成功")
		} else {
			log.Printf("向【" + elem.NickName + "】发送信息失败")
		}
	}
}
